#include <windows.h>
#include "Asura2DEngine/Asura2D.h"
using namespace av2d;

#ifndef _TEST
#include "vermilion.h"
#include "utils.h"
#include "vmath.h"
#include <memory.h>

GLuint base_prog;
GLuint vao;
GLuint quad_vbo;
GLuint tex;

static const char quad_shader_vs[] =
"#version 330 core\n"
"\n"
"layout (location = 0) in vec2 in_position;\n"
"layout (location = 1) in vec2 in_tex_coord;\n"
"\n"
"out vec2 tex_coord;\n"
"\n"
"void main(void)\n"
"{\n"
"    gl_Position = vec4(in_position, 0.5, 1.0);\n"
"    tex_coord = in_tex_coord;\n"
"}\n"
;

static const char quad_shader_fs[] =
"#version 330 core\n"
"\n"
"in vec2 tex_coord;\n"
"\n"
"layout (location = 0) out vec4 color;\n"
"\n"
"uniform sampler2D tex;\n"
"\n"
"void main(void)\n"
"{\n"
"    color = texture(tex, tex_coord);\n"
"}\n"
;

static const GLfloat quad_data[] =
{
	1.0f, -1.0f,
	-1.0f, -1.0f,
	-1.0f, 1.0f,
	1.0f, 1.0f,

	0.0f, 0.0f,
	1.0f, 0.0f,
	1.0f, 1.0f,
	0.0f, 1.0f
};

int main()
{
	EngineDesc desc;
	Engine engine;

	desc.Width = 800;
	desc.Height = 600;
			
	if ( engine.Init(desc) )
	{
		base_prog = glCreateProgram();		
		vglAttachShaderSource(base_prog, GL_VERTEX_SHADER, quad_shader_vs);
		vglAttachShaderSource(base_prog, GL_FRAGMENT_SHADER, quad_shader_fs);

		glGenBuffers(1, &quad_vbo);
		glBindBuffer(GL_ARRAY_BUFFER, quad_vbo);
		
		glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, GL_STATIC_DRAW);

		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);

		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(8 * sizeof(float)));

		glEnableVertexAttribArray(0);
		glEnableVertexAttribArray(1);

		glLinkProgram(base_prog);

		char buf[1024];
		glGetProgramInfoLog(base_prog, 1024, NULL, buf);

		vglImageData image;
		tex = vglLoadTexture("Test/test.dds", 0, &image);
		glTexParameteri(image.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);		
		vglUnloadImage(&image);
		
		while ( engine.BeginFrame() )
		{
			static const vmath::vec3 X(1.0f, 0.0f, 0.0f);
			static const vmath::vec3 Y(0.0f, 1.0f, 0.0f);
			static const vmath::vec3 Z(0.0f, 0.0f, 1.0f);

			glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
			glClearDepth(1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glDisable(GL_CULL_FACE);
			glUseProgram(base_prog);			

			glBindVertexArray(vao);
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
			
			engine.EndFrame();
		}
	}

	glUseProgram(0);
	glDeleteProgram(base_prog);
	glDeleteTextures(1, &tex);
	glDeleteVertexArrays(1, &tex);

	engine.Destroy();

	return 0;
}

#else

#include "ch03_pointsprites.h"
#include "ch03_drawcommands.h"
#include "ch03_instancing.h"
#include "ch03_instancing2.h"
#include "ch03_instancing3.h"
#include "ch06_load_texture.h"
#include "ch06_multi_texture.h"
#include <stdio.h>

int main()
{
	EngineDesc desc;
	Engine engine;

	desc.Width = 1024;
	desc.Height = 768;

	RenderTest *render = nullptr;

	//render = new 
		//ch03_pointsprites
		//ch03_drawcommands
		//ch03_instancing
		//ch03_instancing2
		//ch03_instancing3
		//ch06_load_texture
		//ch06_multi_texture
	;

	if ( engine.Init(desc) && render->Init(desc) )
	{
		if ( GLEW_ARB_debug_output && glDebugMessageCallbackARB != NULL )
			glDebugMessageCallbackARB(&DebugCallback, NULL);

		while ( engine.BeginFrame() )
		{
			render->BeginFrame();
			
			render->EngFrame();
			engine.EndFrame();
		}
	}

	render->Destroy();
	engine.Destroy();

	return 0;
}

#endif